﻿using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;

public class MultiThreadFileCopier
{
    private int copiedFiles = 0;
    private long totalBytes = 0;
    private readonly object lockObject = new object();

    public async Task CopyDirectoryAsync(string sourceDir, string targetDir, int maxThreads = 4)
    {
        if (!Directory.Exists(sourceDir))
        {
            Console.WriteLine($"源目录不存在: {sourceDir}");
            Console.WriteLine("正在创建测试文件和目录...");

            // 自动创建测试目录和文件
            Directory.CreateDirectory(sourceDir);

            // 创建一些测试文件
            CreateTestFiles(sourceDir);
        }

        // 创建目标目录
        Directory.CreateDirectory(targetDir);

        // 获取所有文件
        string[] files = Directory.GetFiles(sourceDir, "*", SearchOption.AllDirectories);
        Console.WriteLine($"找到 {files.Length} 个文件需要拷贝");

        if (files.Length == 0)
        {
            Console.WriteLine("没有文件可拷贝");
            return;
        }

        // 使用信号量控制并发线程数
        using (SemaphoreSlim semaphore = new SemaphoreSlim(maxThreads))
        {
            var tasks = new List<Task>();

            foreach (string file in files)
            {
                await semaphore.WaitAsync();

                tasks.Add(Task.Run(async () =>
                {
                    try
                    {
                        await CopyFileAsync(file, sourceDir, targetDir);
                    }
                    finally
                    {
                        semaphore.Release();
                    }
                }));
            }

            await Task.WhenAll(tasks);
        }

        Console.WriteLine($"\n拷贝完成! 共拷贝 {copiedFiles} 个文件，总大小: {FormatFileSize(totalBytes)}");
    }

    private void CreateTestFiles(string sourceDir)
    {
        // 创建一些测试文件
        string[] testFiles = {
            "document1.txt",
            "image1.jpg",
            "data1.csv",
            "subfolder\\document2.txt",
            "subfolder\\image2.jpg"
        };

        foreach (string file in testFiles)
        {
            string filePath = Path.Combine(sourceDir, file);
            Directory.CreateDirectory(Path.GetDirectoryName(filePath));

            // 创建不同大小的测试文件
            int fileSize = file.Contains("image") ? 1024 * 1024 :  // 1MB for images
                          file.Contains("data") ? 512 * 1024 :     // 512KB for data
                          100 * 1024;                             // 100KB for documents

            byte[] testData = new byte[fileSize];
            new Random().NextBytes(testData);

            File.WriteAllBytes(filePath, testData);
            Console.WriteLine($"创建测试文件: {file} ({FormatFileSize(fileSize)})");
        }
    }

    private async Task CopyFileAsync(string sourceFile, string sourceDir, string targetDir)
    {
        try
        {
            string relativePath = Path.GetRelativePath(sourceDir, sourceFile);
            string targetFile = Path.Combine(targetDir, relativePath);

            // 创建目标目录结构
            Directory.CreateDirectory(Path.GetDirectoryName(targetFile));

            FileInfo fileInfo = new FileInfo(sourceFile);

            using (FileStream sourceStream = new FileStream(sourceFile, FileMode.Open, FileAccess.Read))
            using (FileStream targetStream = new FileStream(targetFile, FileMode.Create, FileAccess.Write))
            {
                await sourceStream.CopyToAsync(targetStream);
            }

            lock (lockObject)
            {
                copiedFiles++;
                totalBytes += fileInfo.Length;
            }

            Console.WriteLine($"已拷贝: {relativePath} ({FormatFileSize(fileInfo.Length)})");
        }
        catch (Exception ex)
        {
            Console.WriteLine($"拷贝文件 {sourceFile} 失败: {ex.Message}");
        }
    }

    private string FormatFileSize(long bytes)
    {
        string[] sizes = { "B", "KB", "MB", "GB" };
        int order = 0;
        double len = bytes;
        while (len >= 1024 && order < sizes.Length - 1)
        {
            order++;
            len /= 1024;
        }
        return $"{len:0.##} {sizes[order]}";
    }
}

// 测试类 - 修改为使用当前目录
class Program
{
    static async Task Main(string[] args)
    {
        MultiThreadFileCopier copier = new MultiThreadFileCopier();

        // 使用当前目录下的测试文件夹，避免权限问题
        string currentDir = Directory.GetCurrentDirectory();
        string sourceDir = Path.Combine(currentDir, "TestSource");
        string targetDir = Path.Combine(currentDir, "TestTarget");

        Console.WriteLine($"源目录: {sourceDir}");
        Console.WriteLine($"目标目录: {targetDir}");

        await copier.CopyDirectoryAsync(sourceDir, targetDir, maxThreads: 4);

        Console.WriteLine("按任意键退出...");
        Console.ReadKey();
    }
}